﻿#ifndef __BYTE_BUFFER_H__
#define __BYTE_BUFFER_H__

#include <vector>
#include <string>
#include "base_type.h"
#include <memory>
#ifndef _WIN32
#include <cstring>
#endif

class ByteBuffer : public std::enable_shared_from_this<ByteBuffer>
{
public:
	enum
	{
		DEFAULT_SIZE = 128,
		MAX_READ_STRING_LEN = 10240,
	};
	ByteBuffer(uint32 bufferSize = DEFAULT_SIZE);
	ByteBuffer(uint8 *data, uint32 bufLen);
	ByteBuffer(ByteBuffer &buf);
	ByteBuffer(ByteBuffer &&buf)noexcept;
	~ByteBuffer() = default;

	ByteBuffer& operator=(const ByteBuffer &buf);
	ByteBuffer& operator=(ByteBuffer &&buf)noexcept;
	const uint8& operator[](const int pos)const;

	void swap(ByteBuffer &buf);
	void setName(const char *s);

	void reset();
	int size();
	void make_writeable_bytes(size_t bytes);
	void reserve(size_t bytes);

	//回收内存
	void gc();

	//可读字节
	int ReadableBytes()const;
	//可写字节
	int WriteableBytes()const;

	//检查可读
	bool CanRead(int s);
	//检查可写
	bool CanWrite(int s);

	uint8* BeginWritePtr();
	const uint8* BeginWriteConstPtr();

	uint8* GetWritePtr();
	uint8* GetReadPtr();

	int AddWritePos(int n);
	int AddReadPos(int n);

	int SetWritePos(int n);
	int SetReadPos(int n);

	int GetWritePos();
	int GetReadPos();

	uint8* begin();
public:
	///write
	int write_int8(const int8 &v);
	int write_int16(const int16 &v);
	int write_int32(const int32 &v);
	int write_int64(const int64 &v);
	int write_float(const float &v);
	int write_double(const double &v);

	int write_uint8(const uint8 &v);
	int write_uint16(const uint16 &v);
	int write_uint32(const uint32 &v);
	int write_uint64(const uint64 &v);

	int write_string(const std::string &v);
	int write_string(const std::string_view &v);
	int write_string(const char *v, int len = 0);

	int write_bytes(const uint8 *v, uint32 len);
	template<class T>
	int write_obj(const T &obj)
	{
		return write_bytes((const uint8*)&obj, sizeof(T));
	}

	///read
	int read_int8(int8 &v);
	int read_int16(int16 &v);
	int read_int32(int32 &v);
	int read_int64(int64 &v);
	int read_float(float &v);
	int read_double(double &v);

	int read_uint8(uint8 &v);
	int read_uint16(uint16 &v);
	int read_uint32(uint32 &v);
	int read_uint64(uint64 &v);

	int read_string(std::string &v);
	int read_string(char *buf, int len);

	int read_bytes(uint8 *v, int len);
	int read_bytes(std::vector<uint8> &buf, int len);
	template<class T>
	int read_obj(T &obj)
	{
		return read_bytes((uint8*)&obj, sizeof(T));
	}

	bool check_read_string_size(int len);
public:
	//根据模板类型读取出字节数
	template<class T>
	T read()
	{
		T data = readByIdx<T>(rPos_);
		int rsize = sizeof(T);
		if (CanRead(rsize) == false)
			return data;
		AddReadPos(rsize);
		if (rPos_ > size())
		{
			rPos_ = 0;
			// LOG_WARNING << "read size overflow rpos:" << rPos_ << " bufsize:" << size();
		}
		return data;
	}

	template<class T>
	T readByIdx(int index) const
	{
		if (index + sizeof(T) <= buf_.size())
			return *((T *)&buf_[index]);
		return 0;
	}

	template<class T>
	int read(T &data, int len)
	{
		if (ReadableBytes() >= len)
		{
			memcpy((void*)&data, (void*)&buf_[rPos_], len);
			AddReadPos(len);
			return len;
		}

		return 0;
	}
	template<class T>
	int read(T &data)
	{
		return read(data, sizeof(T));
	}



	template<class T>
	void append(const T &data)
	{
		append(data, sizeof(T));
	}

	template<class T>
	void insert(T data, int idx)
	{
		int s = sizeof(T);
		if (idx + s > size())
			return;
		memcpy(GetWritePtr() + idx, &data, s);
		wPos_ = idx + s;
	}

	template<class T>
	void append(const T &data, int len)
	{
		reserve(len);
		make_writeable_bytes(len);
		memcpy(GetWritePtr(), &data, len);
		wPos_ += len;
	}

	template<class T>
	ByteBuffer& operator<<(const T &data)
	{
		append(data);
		return *this;
	}


	template<size_t N>
	ByteBuffer& operator<<(char(&data)[N])
	{
		write_uint16((uint16)N);
		write_bytes((uint8*)&data, N);
		return *this;
	}

	template<size_t N>
	ByteBuffer& operator<<(const char(&data)[N])
	{
		write_uint16((uint16)N);
		write_bytes((uint8*)&data, N);
		return *this;
	}

	ByteBuffer& operator<<(const char *data)
	{
		write_string(data);
		return *this;
	}

	ByteBuffer& operator<<(char *data)
	{
		write_string(data);
		return *this;
	}
#ifdef _WIN32
	//template<>
	//ByteBuffer& operator<<(const char *data)
	//{
	//	write_string(data);
	//	return *this;
	//}


	template<>
	ByteBuffer& operator<<(const std::string &str)
	{
		write_string(str);
		return *this;
	}

	template<>
	ByteBuffer& operator<<(const std::string_view &str)
	{
		write_string(str.data());
		return *this;
	}

#endif
	template<class T>
	ByteBuffer& operator>>(T &data)
	{
		read(data);
		return *this;
	}

#ifdef _WIN32
	template<>
	ByteBuffer& operator>>(std::string &str)
	{
		read_string(str);
		return *this;
	}
#endif
	template<size_t N>
	ByteBuffer& operator>>(char(&str)[N])
	{
		uint16 canReadSize = (uint16)ReadableBytes();
		uint16 strSize = 0;
		read_uint16(strSize);
		if (check_read_string_size(strSize) == false)
		{
			// LOG_ERROR << "error buffer size:" << strSize;
			return *this;
		}

		if (strSize > canReadSize)
		{
			strSize = canReadSize;
		}

		//这里直接截取最小值来copy
		uint16 readSize = std::min<uint16>((uint16)N, strSize);
		memcpy_s(str, readSize, GetReadPtr(), readSize);
		AddReadPos(strSize);
		return *this;
	}
public:
	const uint8* constbegin();
	void printInfo();
	void printAH();
	void printAscii();
	void printHex(bool isRead = true);
	void printPosition();

	std::string getHex(bool isRead = true);
private:
	int wPos_ = 0;
	int rPos_ = 0;
	std::vector<uint8> buf_;
	std::string name_;
};

DEFINE_PTR(ByteBuffer)

#endif